﻿module PointerEventTargeting

open System.Windows
open Dom
open Boxes
open Layout


(* only used in rendering and pointer event mapping *)
type AbsPos = AbsPos of int*int
let addPos (AbsPos(ax,ay):AbsPos) (RelPos(rx,ry):RelPos) =
    AbsPos(ax+rx,ay+ry)


let isInside (AbsPos(px,py):AbsPos) ((AbsPos(ax,ay):AbsPos), (BoxSize(width,height):BoxSize))  =
    px>=ax && px<ax+width && py>=ay && py<ay+height

(* Finds the target element by location a point in the layout tree *)    
let rec findTargetElement ((relX,relY),layout) (parentPos:AbsPos) (point:AbsPos) =
    match layout with
    | NoLayout -> None
    | _ ->
        let absPos = addPos parentPos (RelPos(relX,relY))
        if isInside point (absPos, layout.size)
        then                 
            match layout.children |> List.tryPick (fun child-> findTargetElement child absPos point) with
            | None -> layout.element // did not match a child, so return current
            | Some elem -> Some elem // did match a child, return it
        else
            None

let dispatchPointerEvent (layout:Layout) eventName (point:Point) =
    let absPoint = AbsPos(int(point.X), int(point.Y))
    match findTargetElement ((0,0),layout) (AbsPos(0,0)) absPoint with
        | None -> ()
        | Some elem -> 
            let (AbsPos(x,y)) = absPoint
            do elem.dispatchEvent(MouseEvent(eventName, x, y))